/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.niir.goodfil.ui;

import org.apache.log4j.Logger;
import org.h2.util.StringUtils;
import ru.niir.goodfil.audit.util.Assert;
import ru.niir.goodfil.db.*;
import ru.niir.goodfil.exceptions.ValidationException;
import ru.niir.goodfil.ui.utils.FacesUtils;
import ru.niir.goodfil.utils.PriceInfo;
import ru.niir.goodfil.utils.filters.GoodsFilter;

import javax.faces.model.SelectItem;
import javax.faces.model.SelectItemGroup;
import java.util.*;

/**
 * Страница найденных товаров.
 *
 * @author ksazonov
 */
public class ClientGoodsSearchBean extends PageBean {
    private static Logger logger = Logger.getLogger(ClientGoodsSearchBean.class);

    private static final int MODE_GOODTYPE = 1;
    private static final int MODE_SEARCH = 2;
    
    private int currentMode;

    public boolean getModeIsSearch() {
        return currentMode == MODE_SEARCH;
    }

    public boolean getModeIsGoodType() {
        return currentMode == MODE_GOODTYPE;
    }
    
    private String searchParamOe;
    private Long searchParamGoodTypeId;
    private String searchParamGoodTypeName;
    private String tableTitle;

    private Long clientId;
    private Client client;
    private Map<Long/**/, Long/**/> clientgroupsAssigment = getClientgroupsAssigmentForGuests();

    private List<Good> goodsCache;

    private List<Good> getGoodsCache() {
        if (goodsCache == null) {
            GoodsFilter goodsFilter = new GoodsFilter();
            goodsFilter.setDeleted(0);
            goodsCache = gf().getGoods(0, Integer.MAX_VALUE, goodsFilter);
        }
        return goodsCache;
    }

    private Map<Long, Long> getClientgroupsAssigmentForGuests() {
        Map<Long, Long> result = new HashMap<Long, Long>();
        List<ClientGroup> clientgroups = gf().getClientGroups();
        for(Brand brand : gf().getBrands()) {
            for (ClientGroup clientGroup : clientgroups) {
                if (clientGroup.getBrandId() == brand.getId() && clientGroup.isShown()) {
                    result.put(brand.getId(), clientGroup.getId());
                }
            }
        }
        return result;
    }

    private final List<Good> goods = new ArrayList<Good>();

    public void searchByGoodType() {
        goods.clear();

        if (searchParamGoodTypeId != null) {
            List<Good> foundGoods = gf().getGoodsWithPrices2(0, Integer.MAX_VALUE, searchParamGoodTypeId);
            for (Good good : foundGoods) {
                if (good.isDeleted()) continue;
                this.goods.add(good);
            }
        }
        
        GoodType goodType = gf().getGoodTypeById(searchParamGoodTypeId);
        tableTitle = goodType.getName();
        searchParamGoodTypeName = goodType.getName();
        currentMode = MODE_GOODTYPE;

        searchParamOe = "";
    }

    public static String mask(String s) {
        StringBuilder sb = new StringBuilder();
        for (char c : s.toCharArray()) {
            if (Character.isLetter(c) || Character.isDigit(c)) {
                sb.append(Character.toUpperCase(c));
            }
        }
        return sb.toString();
    }

    public void searchByOe() {
        goods.clear();

        Set<Long> goodsIds = new HashSet<Long>();
        searchParamOe = mask(searchParamOe);
        if (!StringUtils.isNullOrEmpty(searchParamOe)) {
            for (Good good : getGoodsCache()) {
                if (mask(good.getCode()).startsWith(searchParamOe)) {
                    goodsIds.add(good.getId());
                }
            }
        }

        if (goodsIds.size() > 0) {
            this.goods.addAll(gf().getGoodsWithPrices(goodsIds));
        }
        
        tableTitle = "Результаты поиска по запросу: " + searchParamOe;
        currentMode = MODE_SEARCH;
    }

    public void init(Long clientId) {
        Assert.notNull(clientId);
        this.clientId = clientId;

        Client client = gf().getClientById(clientId);
        Assert.notNull(client);
        this.client = client;

        this.clientgroupsAssigment = client.getClientgroups();

        getGoodsCache();
    }

    public List<Good> getGoods() {
        return goods;
    }


    public Map<Long/**/, Long/**/> getClientgroupsAssigment() {
        return clientgroupsAssigment;
    }


    /**
     * -------------------------------------------------------------------------
     * ----------Работа с БД----------
     * -------------------------------------------------------------------------
     */

    private long goodId;
    private int goodCount;
    private int goodMaxCount;

    /**
     * Добавить товар в заказ.
     */
    public void addGoodInOrder() {
        try {
            Good good = gf().getGoodById(goodId);
            if (good.getC1CodeIsMissing()) {
                throw new IllegalArgumentException("Для указанного товара нет кода соответствия 1С: " + goodId);
            }

            if (goodCount < 0) facesError("Количество добаляемого товара должно быть положительным числом");
            //  Проверяем что данный заказ вообще можно изменять
            if (!getSessionBean().getOrder().getOrderStateIsBeforeSaved()) {
                facesError("Выбранный заказ находится на оформлении и изменять его нелья");
            }

            //  Получаем элементы заказа
            List<OrderItem> orderItems = getSessionBean().getOrderItems();

            //  Проводим склейку
            for (OrderItem orderItem : orderItems) {
                if (orderItem.getGoodId() == good.getId()) {

                    //  EXPERIMETNAL: Отключено для предотвращения ошибки повторной выборки товара
                    if (good.getCount() < (orderItem.getCount() + goodCount)) {
                        facesError("Указанного количества товара нет в наличии");
                    }

                    //  Склеиваем
                    if (hasFacesErrors()) return;
                    orderItem.setCount(orderItem.getCount() + goodCount);
                    getSessionBean().setOrderItems(orderItems);
                    facesInfo("Количество товара " + good.getName() + " " + good.getCode() + " изменено");
                    return;
                }
            }

            //  Добавляем в заказ новую позицию
            if (hasFacesErrors()) return;

//          BRANDS
//            PriceInfo pi = gf().getPrice(good.getId(),
//                                       getSessionBean().getSelectedClientId(),
//                                       getSessionBean().getSelectedClientGroupId());
            PriceInfo pi = gf().getPrice2(good.getId(),
                    good.getBrandId(),
                    getSessionBean().getSelectedClientId(),
                    getSessionBean().getSelectedClientGroupId2(good.getBrandId()));
            OrderItem orderItem = new OrderItem();

            orderItem.setGoodId(good.getId());
            orderItem.setOrderId(getSessionBean().getSelectedOrderId());
            orderItem.setCount(goodCount);
            orderItem.setStartPrice(pi.getPrice());
            orderItem.setPersonalPrice(pi.isPersonalPrice());
            logger.debug("Good " + good.getId() + " added with startPrice: " + pi.getPrice());
            orderItem.setPersonalPrice(pi.isPersonalPrice());

            orderItems.add(orderItem);

            orderItem.setGood(good);

            getSessionBean().setOrderItems(orderItems);

            facesInfo("Товар " + good.getName() + " " + good.getCode() + " (" + goodCount + " шт.) добавлен к заказу");
        } catch (Exception e) {
            facesError("Не удалось добавить товар в заказ");
            e.printStackTrace();
        }
    }

    public List<SelectItem> getClientGroupsSelectItems() {
        List<SelectItem> result = new ArrayList<SelectItem>();

        ClientGoodsBean clientGoodsBean = (ClientGoodsBean) FacesUtils.getManagedBean("ClientGoodsBean");
        for (GoodType goodType : clientGoodsBean.getGoodTypes()) {

            List<SelectItem> childrenSelectItems = new ArrayList<SelectItem>();
            for (GoodType childGoodType : goodType.getChildren()) {
                childrenSelectItems.add(new SelectItem(childGoodType.getId(), childGoodType.getName()));
            }

            SelectItem[] arr = new SelectItem[childrenSelectItems.size()];
            childrenSelectItems.toArray(arr);
            result.add(new SelectItemGroup(goodType.getName(), null, false, arr));
        }

        return result;
    }
    
    /**
     * Полчить максимальное количество товара для отображения ("в наличии")
     */
    public int getViewGoodsCount() {
        gf().createIfNotExists("view.goods.count", 200);
        return gf().getInt("view.goods.count");
    }

    public long getGoodId() {
        return goodId;
    }

    public void setGoodId(long goodId) {
        this.goodId = goodId;
    }

    public int getGoodCount() {
        return goodCount;
    }

    public void setGoodCount(int goodCount) {
        this.goodCount = goodCount;
    }

    public int getGoodMaxCount() {
        return goodMaxCount;
    }

    public void setGoodMaxCount(int goodMaxCount) {
        this.goodMaxCount = goodMaxCount;
    }

    public String getTableTitle() {
        return tableTitle;
    }

    public String getSearchParamOe() {
        return searchParamOe;
    }

    public void setSearchParamOe(String searchParamOe) {
        this.searchParamOe = searchParamOe;
    }

    public Long getSearchParamGoodTypeId() {
        return searchParamGoodTypeId;
    }

    public void setSearchParamGoodTypeId(Long searchParamGoodTypeId) {
        this.searchParamGoodTypeId = searchParamGoodTypeId;
    }

    public String getSearchParamGoodTypeName() {
        return searchParamGoodTypeName;
    }
}
